#include <am.h>

#include <klib-macros.h>
#include <klib.h>
#include <stdarg.h>
#include <stddef.h>

#if !defined(__ISA_NATIVE__) || defined(__NATIVE_USE_KLIB__)

//设计vprintf 和辅助函数
//需要实现一个基本的格式化解析器，他将会处理不同的格式标志，并根据对应的参数输出。

void itoa(int value, char *str, int base) {
    // 保存原始值，用于处理负数
    //int tmp_value = value;
    int i = 0;
    
    // 处理负数
    if (value < 0 && base == 10) {
        str[i++] = '-';
        value = -value;  // 变为正数
    }

    // 处理特殊值0
    if (value == 0) {
        str[i++] = '0';
        str[i] = '\0';
        return;
    }

    // 转换整数到字符串，逆序存储
    char digits[] = "0123456789ABCDEF";  // 十六进制支持
    int temp_value = value;  // 临时变量来处理转换
    char buffer[32];         // 假设最大32位整数
    int j = 0;

    // 对整数进行除基操作，存储每一位的字符
    while (temp_value) {
        buffer[j++] = digits[temp_value % base];  // 获取当前位
        temp_value /= base;  // 继续除以基数
    }

    // 将结果逆序存储
    for (int k = 0; k < j; k++) {
        str[i++] = buffer[j - 1 - k];
    }

    // 以null字符结束字符串
    str[i] = '\0';
}

void vprintf(const char *format, va_list args) {
  const char *ptr = format;
  while (*ptr != '\0') {
    if (*ptr == '%') {
      ptr++; //这里是指向具体的格式。
      switch (*ptr) {
      case 'd': {
        int value = va_arg(args, int);
        //将整数数值转换为字符串并逐个字符输出。
        char buf[20];
        itoa(value, buf, 10);
        for (int i = 0; buf[i] != '\0'; i++)
          putch(buf[i]);
        break;
      }
      case 's': {
        const char *str = va_arg(args, const char *);
        while (*str)
          putch(*str++);
        break;
      }
      case 'c': {
        char ch = (char)va_arg(args, int);
        putch(ch);
        break;
      }
      default:
        putch('%');
        putch(*ptr);
        break;
      }
    } else {
      putch(*ptr);
    }
    ptr++;
  }
}

int printf(const char *fmt, ...) {
  va_list args;
  va_start(args, fmt);
  vprintf(fmt, args);
  va_end(args);
  return 0;
  // panic("Not implemented");
}

int vsprintf(char *out, const char *fmt, va_list ap) {
  char *ptr = out;
  const char *fmt_ptr = fmt;
  while (*fmt_ptr != '\0') {
    if (*fmt_ptr == '%') {
      fmt_ptr++;
      switch (*fmt_ptr) {
      case 'd': {
        int value = va_arg(ap, int);
        char buf[20];
        itoa(value, buf, 10);
        char *buf_ptr = buf;
        while (*buf_ptr) {
          *ptr = *buf_ptr;
          ptr++;
          buf_ptr++;
        }
        break;
      }
      case 's': {
        const char *str_value = va_arg(ap, const char *);
        while (*str_value) {
          *ptr++ = *str_value++;
        }
        break;
      }
      case 'c': {
        char ch = (char)va_arg(ap, int);
        *ptr++ = ch;
        break;
      }
      default:
        *ptr++ = '%';
        *ptr++ = *fmt_ptr;
        break;
      }
    } else {
      *ptr++ = *fmt_ptr;
    }
    fmt_ptr++;
  }
  *ptr = '\0';
  return ptr - out;
  // panic("Not implemented");
}

int sprintf(char *out, const char *fmt, ...) {

  va_list args;
  va_start(args, fmt);
  int ret = vsprintf(out, fmt, args);
  va_end(args);
  return ret;
  //panic("Not implemented");
}

int snprintf(char *out, size_t n, const char *fmt, ...) {
  va_list args;
  va_start(args, fmt);
  int ret = vsnprintf(out, n, fmt, args);
  va_end(args);
  return ret;
  //panic("Not implemented");
}

int vsnprintf(char *out, size_t n, const char *fmt, va_list ap) {
  char *ptr = out;
  const char *fmt_ptr = fmt;
  size_t count = n - 1; //留一个地方给\0
  while (*fmt_ptr != '\0' && count > 0) {
    if (*fmt_ptr == '%') {
      fmt_ptr++;
      switch (*fmt_ptr) {
      case 'd': {
        int value = va_arg(ap, int);
        char buf[20];
        itoa(value, buf, 10);
        while (*buf && count > 0) {
          *ptr++ = (*buf)++;
          count--;
        }
        break;
      }
      case 's': {
        const char *str_value = va_arg(ap, const char *);
        while (*str_value && count > 0) {
          *ptr++ = *str_value++;
          count--;
        }
        break;
      }
      case 'c': {
        char ch = (char)va_arg(ap, int);
        *ptr++ = ch;
        count--;
        break;
      }
      default:
        *ptr++ = '%';
        *ptr++ = *fmt_ptr;
        count--;
        break;
      }
    }else {
      *ptr++ = *fmt_ptr;
      count--;
    }
    fmt_ptr++;
  }
  // panic("Not implemented");
  *ptr ='\0';
  return ptr -out;
}

#endif
